package se.gala.games.quetzalcoatl;

import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import se.gala.api.APICommand;
import se.gala.api.APIParameter;
import se.gala.api.GenericAPICommands;
import se.gala.api.GenericParameters;
import se.gala.core.M3GMove;
import se.gala.gw.GWClient;
import se.gala.utils.Coordinate2D;
import se.gala.utils.Logger;
import se.gala.utils.MoneyInt;
import se.gala.wallet.BalanceTypes;
import se.gala.wallet.InsufficientFundsException;

public class UIQuetzalcoatl extends Application {
	private static Quetzalcoatl qgame;
	protected static Parent root;
	protected static Scene scene;
	private static Player player;
	private static Balance balance;
	private static Hashtable<String, GemButton> gems = new Hashtable<String, GemButton>(64);
	private static QBet bet;
	protected static MoneyInt stakeAmount;
	protected static UIQController uiqc;
	protected static final int SCENE_WIDTH = 480;
	protected static final int SCENE_HEIGHT = 480;
	protected static final int GEM_WIDTH = 50;
	protected static final int GEM_HEIGHT = 50;
	
	@Override
	public void start(Stage primaryStage) {
		QSymbols.NONE.setColorAndBg("255, 255, 255", "b_none", "gem-none");
		QSymbols.Copper.setColorAndBg("217, 144, 88", "b_copper", "gem-copper");
		QSymbols.Emerald.setColorAndBg("80, 200, 120", "b_emerald", "gem-emerald");
		QSymbols.Gold.setColorAndBg("255, 215, 0", "b_gold", "gem-gold"); 
		QSymbols.Jade.setColorAndBg("0, 92, 58", "b_jade", "gem-jade"); 
		QSymbols.Obsidian.setColorAndBg("225, 225, 225", "b_obsidian", "gem-obsidian"); 
		QSymbols.Ruby.setColorAndBg("209, 0, 86", "b_ruby", "gem-ruby");
		QSymbols.Sapphire.setColorAndBg("51, 51, 153", "b_sapphire", "gem-sapphire"); 
		QSymbols.Silver.setColorAndBg("0, 0, 0", "b_silver", "gem-silver"); 
		QSymbols.Stone.setColorAndBg("102, 102, 102", "b_stone", "gem-stone"); 
		QSymbols.Turquoise.setColorAndBg("52, 221, 221", "b_turquoise", "gem-turquoise");
		
		try {
			root = FXMLLoader.load(getClass().getResource("QInterface.fxml"));
			scene = new Scene(root, SCENE_WIDTH, SCENE_HEIGHT);
			scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
			primaryStage.setTitle("Quetzalcoatl");
			primaryStage.setScene(scene);
			primaryStage.show();
			primaryStage.setResizable(false);
		} catch(Exception e) {
			e.printStackTrace();
		}
		
		UIAnimationFactory.doInitialAnimation();
	}
	
	protected static void doReshuffle() {
		qgame.doReshuffle(true);
		UIAnimationFactory.doShakerAnimation();
	}
	
	protected static void doRestart() {
		qgame.doReshuffle(false);
		UIAnimationFactory.doClosingAnimation(true);
	}
	
	protected static void doRandom() {
		boolean betPlaced = UIQuetzalcoatl.doPlaceBet();
		if (betPlaced) {
			qgame.doRandomReshuffle(false);
			UIAnimationFactory.doClosingAnimation(true);
		}
	}

	protected static void doStoneCrash() {
		boolean betPlaced = UIQuetzalcoatl.doPlaceBet();
		if (betPlaced) {
			qgame.crashAllAtLevel(QLevels.Level0);
			UIAnimationFactory.doStoneCrashBoosterAnimation();
		}
	}

	protected static void doRandomMove() {
		boolean betPlaced = UIQuetzalcoatl.doPlaceBet();
		if (betPlaced) {
			M3GMove mv = qgame.determineRandomMove(false);
			UIAnimationFactory.doSwapGemsAnimation(mv, true, true, true);
		}
	}
	
	protected static void doBestMove() {
		boolean betPlaced = UIQuetzalcoatl.doPlaceBet();
		if (betPlaced) {
			M3GMove mv = qgame.determineTheBestMove();
			UIAnimationFactory.doSwapGemsAnimation(mv, true, true, true);
		}
	}
	
	protected static boolean checkForWinnings() {
		return qgame.checkForWinnings();
	}
	
	protected static boolean doPlaceBet() {
		bet = new QBet(stakeAmount.getCentValueAsInt(), QStakes.MoveDefault, QBetValues.QBV_Move);
		qgame.placeBet(bet);
		try {
			player.registerBet(BalanceTypes.CashBalancePlayable, stakeAmount.getCopy(), qgame.getGameId());
		} catch (InsufficientFundsException e) {
			log("+-+-+-+-+-+-+-+-+-+-+-+-+");
			log("+ INSUFFICIENT BALANCE  +");
			log(e.getMessage());
			log("+-+-+-+-+-+-+-+-+-+-+-+-+");
			return false;
		}
		return true;
	}
	
	protected static void burnWinnings() {
		qgame.setWinning();
		UIAnimationFactory.doBurnAnimation(qgame.getGemsToBurn());
		player.registerWin(BalanceTypes.CashBalancePlayable, balance.moneyIntFactory(qgame.getWinning()), qgame.getGameId());
	}
	
	
	protected static HashSet<GemButton> getPossibleMatches(GemButton gb) {
		QuetzalSymbol s = gb.getQuetzalSymbol();
		Coordinate2D c = gb.getCoordinates();
		Coordinate2D c1 = new Coordinate2D(c.x - 1, c.y);
		Coordinate2D c2 = new Coordinate2D(c.x + 1, c.y);
		Coordinate2D c3 = new Coordinate2D(c.x, c.y - 1);
		Coordinate2D c4 = new Coordinate2D(c.x, c.y + 1);
		HashSet<GemButton> matches = new HashSet<GemButton>();
		if (qgame.isMoveLegal(c, c1, s)) {
			matches.add(getGemByCoordinate(c1));
		}
		if (qgame.isMoveLegal(c, c2, s)) {
			matches.add(getGemByCoordinate(c2));
		}
		if (qgame.isMoveLegal(c, c3, s)) {
			matches.add(getGemByCoordinate(c3));
		}
		if (qgame.isMoveLegal(c, c4, s)) {
			matches.add(getGemByCoordinate(c4));
		}
		return matches;
	}
	
	protected static void higlightPossibleMatches(GemButton gb, boolean switchOn) {
		HashSet<GemButton> m = gb.getMatchingNeighbours();
		for (GemButton gem : m) {
			gem.setSelected(switchOn);
		}
	}
	
	protected static void swapGems(GemButton gb1, GemButton gb2) {
		qgame.getMatrix().swapSymbols(gb1.getCoordinates(), gb2.getCoordinates());
	}
	
	protected static Hashtable<String, GemButton> getGems() {
		return gems;
	}
 	
	protected static Quetzalcoatl getGame() {
		return qgame;
	}
	
	protected synchronized static void repaintGems() {
		Set<String> keys = gems.keySet();
		for (String key: keys) {
			gems.get(key).repaint();
		}
	}
	
	protected static GemButton getGemByCoordinate(Coordinate2D c) {
		return gems.get("b" + c.y + c.x);
	}
	
	protected static void register(GemButton btn) {
		gems.put(btn.getId(), btn);
	}
	
	protected static Balance getBalance() {
		return balance;
	}
	
	protected static void setPlayer(String sessionToken) {
		player = new Player(sessionToken);
	}
	
	public static void test(int credit, int stake, String user, String pass, String[] args) {
		APICommand c = GenericAPICommands.factory(GenericAPICommands.AuthenticateWithPassword_Request, new APIParameter[] {
				GenericParameters.factory(GenericParameters.Username, user), 
				GenericParameters.factory(GenericParameters.Password, pass)});
		GWClient.sendClientRequest(c, true, DefaultResponseHandler.getInstance());
//		log("\ntova ne triabva da se pokazva predi blokajat ot sendClientRequest da e svarshil.");
		
		// FIXME UIQuetzalcoatl initiation !!!!!
		balance = player.getBalance();
		
		balance.setRealCashBalance(balance.moneyIntFactory(credit));
		stakeAmount = balance.moneyIntFactory(stake);
//		qgame = Quetzalcoatl.doHistoricGame(1541535246993396987L);
		qgame = new Quetzalcoatl();
		launch(args);
	}

	private static void log(Object o) {
		Logger.log(o);
	}
	
	public static String resolveURI(String filename) {
		return UIQuetzalcoatl.class.getResource(filename).toExternalForm();
	}
	
}
